#ifndef __YLIB_LRU_H
#define __YLIB_LUR_H

#include "sysy_lib.h"
#include "list.h"

/** @file LRU cache
 *
 * entry: lru_entry_t
 * value: lru_entry_t->value
 * key: getkey_func(value)
 */

// key -> hash
typedef uint32_t (*lru_key_func)(const void *key);

// value -> key*
typedef void* (*lru_getkey_func)(const void *value);

typedef int (*lru_cmp_func)(const void *value, const void *key);

typedef int (*lru_load_func)(void *key, void **value);

typedef void (*lru_unload_func)(void *lru_entry);

// need free, as hashtable_entry_t->value
typedef struct {
        struct list_head hook;
        // point to queue item
        struct list_head *pos;
        // NOTE: need free, loaded in load_func
        void *value;
} lru_entry_t;

typedef struct {
        hashtable_t table;
        struct list_head queue;
        int size;
        int capacity;
        //
        lru_getkey_func getkey_func;
        lru_load_func load_func;
        lru_unload_func unload_func;
} lru_t;

int lru_init(lru_t **lru, int capacity,
             lru_cmp_func cmp_func,
             lru_key_func key_func,
             lru_getkey_func getkey_func,
             lru_load_func load_func,
             lru_unload_func unload_func);
int lru_destroy(lru_t **lru);

/**
 *
 * @param lru
 * @param key
 * @param value
 * @return  lru_entry_t->value
 */
int lru_get(lru_t *lru, void *key, void **value);

int lru_dump(lru_t *lru, int (*handler)(void *arg, void *entry));

#endif
